package ru.niir.goodfil.ui;

import org.apache.log4j.Logger;
import ru.niir.goodfil.db.GoodType;
import ru.niir.goodfil.exceptions.CreateFailureException;
import ru.niir.goodfil.exceptions.ValidationException;
import ru.niir.goodfil.utils.validation.CreateCheckResult;
import ru.niir.goodfil.utils.validation.ValidationError;
import ru.niir.goodfil.utils.validation.ValidationResult;

import javax.faces.model.SelectItem;
import java.util.ArrayList;
import java.util.List;

/**
 * Бин для работы с группами товаров.
 */
public class GoodTypesBean extends PageBean {
    private static Logger logger = Logger.getLogger(GoodTypesBean.class);

    /**
     * Узлы девера групп товаров
     */
    private List<GoodType> goodTypes;
    /**
     * Текущая группа
     */
    private GoodType goodType = new GoodType();

    /**
     * Родительское имя
     */
    private String parentName;
    /***/
    private long goodTypeIdFrom;
    /***/
    private long goodTypeIdTo;
    /***/
    private boolean showHidden;

    /**
     *
     */
    public GoodTypesBean() {
        logger.debug("> " + buildGoodTypeTree().collect().size());
        logger.debug("> " + buildGoodTypeTree().collectNotDeleted().size());
    }

    /**
     * Возвращает текущую группу товаров.
     *
     * @return группа товаров
     */
    public GoodType getGoodType() {
        return goodType;
    }

    /**
     * Возвращает родительское имя.
     *
     * @return родительское имя
     */
    public String getParentName() {
        return parentName;
    }

    /**
     * Устанавливает родительское имя.
     *
     * @param parentName родительское имя
     */
    public void setParentName(String parentName) {
        this.parentName = parentName;
    }

    /**
     * @param goodTypeIdFrom
     */
    public void setGoodTypeIdFrom(long goodTypeIdFrom) {
        this.goodTypeIdFrom = goodTypeIdFrom;
    }

    /**
     * @return
     */
    public long getGoodTypeIdFrom() {
        return goodTypeIdFrom;
    }

    /**
     * @param goodTypeIdTo
     */
    public void setGoodTypeIdTo(long goodTypeIdTo) {
        this.goodTypeIdTo = goodTypeIdTo;
    }

    /**
     * @return
     */
    public long getGoodTypeIdTo() {
        return goodTypeIdTo;
    }

    /**
     * @param showHidden
     */
    public void setShowHidden(boolean showHidden) {
        this.showHidden = showHidden;
    }

    /**
     * @return
     */
    public boolean getShowHidden() {
        return showHidden;
    }

    /**
     * Построить дерво групп товаров и вернуть его корневой узел ("Корневая группа")
     */
    private GoodType buildGoodTypeTree() {
        List<GoodType> nodesList = gf().getGoodTypes();

        for (GoodType gt : nodesList) gt.getChildren().clear();

        GoodType rootGroodType = null;
        for (int i = 0; i < nodesList.size(); i++) {
            GoodType n1 = nodesList.get(i);
            if (n1.getId() == 1) rootGroodType = n1;

            for (int j = 0; j < nodesList.size(); j++) {
                if (i == j) continue;

                GoodType n2 = nodesList.get(j);
                if (n2.getParentId() != null && n2.getParentId() == n1.getId()) {
                    n1.getChildren().add(n2);
                    n2.setParent(n1);
                }
            }
        }

        assert rootGroodType != null;
        rootGroodType.setLevel(0);
        rootGroodType.setParent(rootGroodType);

        return rootGroodType;
    }

    /**
     * @return
     * @throws NotRequestedException
     */
    public List<GoodType> getGoodTypes() {
        logger.debug("getGoodTypes()");
        if (goodTypes == null) {
            logger.debug("..loading good types");
            if (showHidden) {
                logger.debug("..all");
                goodTypes = buildGoodTypeTree().collect();
            } else {
                logger.debug("..not deleted");
                goodTypes = buildGoodTypeTree().collectNotDeleted();
            }
        }
        logger.debug("..result: " + goodTypes.size());
        return goodTypes;
    }

    /**
     * @return
     */
    public List<SelectItem> getGoodTypesAsSelectItems() {
        List<SelectItem> result = new ArrayList<SelectItem>();
        List<GoodType> gts = gf().getGoodTypes();
        result.add(new SelectItem(-1, "Не установлена"));
        for (GoodType gt : gts) result.add(new SelectItem(gt.getId(), gt.getName()));
        return result;
    }

    public List<SelectItem> getGoodTypesAsSelectItems2() {
        List<SelectItem> result = new ArrayList<SelectItem>();
        List<GoodType> gts = gf().getGoodTypesRecursivelyByParentId(1, false);
        for (GoodType gt : gts) {
            if (!gt.isDeleted()) {
                StringBuilder sb = new StringBuilder();
                for (int i = 1; i < gt.getLevel(); i++) sb.append("&nbsp;&nbsp;&nbsp;&nbsp;");

                SelectItem selectItem = new SelectItem(gt.getId(), sb.toString() + gt.getName());
                selectItem.setEscape(false);
                result.add(selectItem);
            }
        }
        return result;
    }

    /**
     *
     */
    public void invertShowHidden() {
        logger.debug("showHidden was: " + showHidden);
        showHidden = !showHidden;
        goodTypes = null;
        logger.debug("showHidden now: " + showHidden);
    }


    /**
     * -------------------------------------------------------------------------
     * ----------Работа с БД----------
     * -------------------------------------------------------------------------
     */

    /**
     * Создание/редактирование группы товаров.
     */
    public void saveGoodType() throws ru.niir.goodfil.exceptions.ValidationException {
        if (getGoodType().getId() == -1) {
            //  Новая группа
            if (!gf().isGoodTypeNameUniqueByParent(getGoodType().getName(), getGoodType().getParentId()))
                facesError("Наименование группы должно быть уникально");

            if (hasFacesErrors()) return;

            try {
                gf().saveGoodType(getGoodType());
                facesInfo("Группа товаров сохранена");
            } catch (ValidationException ex) {
                logger.error(ex);
                ex.printStackTrace();
                ValidationResult validationResult = ex.getResult();
                for (ValidationError error : validationResult.getErrors())
                    facesError(error.toHumanString());
            } catch (CreateFailureException ex) {
                logger.error(ex);
                ex.printStackTrace();
                CreateCheckResult createCheckResult = ex.getResult();
                facesError(createCheckResult.getMsg());
            }
        } else {
            //  Редактирование
            if (!gf().isGoodTypeNameUnique(getGoodType().getName(), getGoodType().getId()))
                facesError("Наименование группы должно быть уникально");

            if (hasFacesErrors()) return;

            try {
                gf().updateGoodType(getGoodType());
                facesInfo("Группа товаров изменена");
            } catch (ValidationException ex) {
                logger.error(ex);
                ex.printStackTrace();
                ValidationResult validationResult = ex.getResult();
                for (ValidationError error : validationResult.getErrors())
                    facesError(error.toHumanString());
            }
        }
    }

    /**
     * Удаление группы с идентификатором deleteGroupId
     */
    public void deleteGoodType() {
        gf().softRemoveGoodTypeById(goodType.getId());
    }

    /**
     * Перемещение группы товаров
     */
    public void moveGoodType() {
        logger.debug("moveGoodType1");

        /*
        Какие проверки должны быть:

        1. Нельзя переместить группу в себя
        2. Нельзя переместить группу в дочернюю по отношению к ней группу
         */

        GoodType goodType = new GoodType();

        List<GoodType> goodTypes = buildGoodTypeTree().collectNotDeleted();
        for (GoodType gt : goodTypes)
            if (gt.getId() == goodTypeIdFrom)
                goodType = gt;

        List<GoodType> children = goodType.collect();
        for (GoodType child : children)
            if (child.getId() == goodTypeIdTo)
                facesError("Нелья переместить группу в саму себя или в дочернюю по отношению к ней");

        if (hasFacesErrors()) return;

        try {
            /*
             * Собственно перемещение
             */
            goodType.setParentId(goodTypeIdTo);
            gf().updateGoodType(goodType);
            facesInfo("Группа перемещена");
        } catch (Exception e) {
            facesError(e.getClass().getName());
            e.printStackTrace();
        }

        this.goodTypes = null;
    }

    //
    //  Сохранение привязки группы товаров к брэнду
    //

    public void saveGoodTypeBrand() {
        long goodTypeId = Long("goodTypeId");
        long brandId = Long("brandId");
        Long lBrandId = brandId != 0 ? brandId : null;

        gf().saveGoodTypeBrand(goodTypeId, lBrandId);
    }

}